# Copyright (c) P SOFTHOUSE. All rights reserved.
# -*- coding: utf-8 -*-
import os
import site
import locale
import sys
import _winreg as reg
import subprocess

# Using Qt.py for backward compatibility with PySide (used by Maya 2016.5 and older).
from PSOFT.vendor.Qt_py.Qt import QtWidgets, QtCore

from functools import cmp_to_key
from cStringIO import StringIO

import maya.cmds as cmds  # pylint: disable=E0401
import maya.mel as mel  # pylint: disable=E0401
import xml.etree.ElementTree as xml

# PySide2 is used by Maya 2017 and up. PySide is used by older versions of Maya.
try:
    import pyside2uic as pysideuic
except ImportError:
    import pysideuic


"""
    Localize
"""
def getLocalizedString(key):
    return mel.eval('getPluginResource("Pencil+4", "{0}")'.format(key))

"""
    TextField utils.
"""
def setText(field, newText):
    cmds.textField(field, edit=True, text=newText)

def getText(field):
    return cmds.textField(field, query=True, text=True)

"""
    Button utils.
"""
def setButtonEnabled(button, isEnabled):
    cmds.button(button, edit=True, enable=isEnabled)

def fixDialogSize(control_path=None):
    """
    親ダイアログウインドウのサイズ変更可能フラグを落とします
    control_path    ダイアログ内のコントロールパスです。ここから親ダイアログを検索します
                    Noneを指定すればsetParent(q=True)を実行し、現在のパスを検索対象とします
    """
    if not control_path:
        control_path = cmds.setParent(q=True)
    controls = control_path.split('|')

    for i, ctrl in enumerate(controls):
        if ctrl.lower().find('dialog') >= 0:
            dlg_path = '|'.join(controls[:i+1])
            cmds.window(dlg_path, edit=True, sizeable=False, maximizeButton=False, minimizeButton=False)
            return dlg_path
    return ""

def getModuleName():
    """
    Returns the name of the Pencil+ 4 module.
    """
    return 'Pencil_4'

def getModulePath():
    """
    Returns the path of our module.
    """
    return cmds.getModulePath(moduleName=getModuleName())

"""
Launch the specified tool.

param: String identifying the tool. Case insensitive.
  Supported values:
    SLSetting - Standalone license tool.
    NLSetting - Network license tool.
"""
def launchPencilTool(toolName, isModal=False):
    is_japanease = mel.eval('about -uiLanguage') == 'ja_JP'
    execfname = ""
    options = []

    if toolName.lower() == 'slsetting':
        execfname = "SLSetting_x64_Pencil+ 4 for Maya.exe"
        options = ["/lang", "JP"] if is_japanease else ["/lang", "EN"]
    elif toolName.lower() == 'nlsetting':
        execfname = "NLSetting_x64_Pencil+ 4 for Maya.exe"
        options = ["/ja"] if is_japanease else ["/en"]
    else:
        cmds.warning('launchPencilTool() - Unknown tool ' + toolName + '.')
        return

    exe_path = getModulePath() + "/tools/" + execfname  # unicode string （このままsubprocessに渡すと失敗するのでmbcsに変換する）
    args = [exe_path.encode(sys.getfilesystemencoding())] + options
    try:
        proc = subprocess.Popen(args)
        # ユーザーが直接ツールを起動していた場合は、ツールの2重起動防止機能によりすぐ終了してしまうので、
        # 待つことはできません。
        if isModal:
        	proc.communicate()
    except WindowsError as e:
        cmds.warning(str(e) + ' - ' + str(args))


# Retrieved from URL https://gist.github.com/liorbenhorin/217bfb7e54c6f75b9b1b2b3d73a1a43a on 2017-07-05
# Not copyrighted
def loadUiType(uiFile):
    """
	:author: Jason Parks
	Pyside lacks the "loadUiType" command, so we have to convert the ui file to py code in-memory first
	and then execute it in a special frame to retrieve the form_class.
	"""
    parsed = xml.parse(uiFile)
    widget_class = parsed.find('widget').get('class')
    form_class = parsed.find('class').text

    with open(uiFile, 'r') as f:
        o = StringIO()
        frame = {}

        pysideuic.compileUi(f, o, indent=0)
        pyc = compile(o.getvalue(), '<string>', 'exec')
        exec pyc in frame

        # Fetch the base_class and form class based on their type in the xml from designer
        form_class = frame['Ui_%s' % form_class]
        base_class = getattr(QtWidgets, widget_class)

    return form_class, base_class

def sortStrings(input):
    # Without setting the default locale, sorting does not handle case properly
    # Save the current locale setting
    loc = locale.getlocale(locale.LC_COLLATE)
    # Set to the default locale for sorting strings
    locale.setlocale(locale.LC_COLLATE, '')

    output = sorted(input, key=cmp_to_key(locale.strcoll))

    # Restore the original locale
    locale.setlocale(locale.LC_COLLATE, loc)

    return output

# Executes the specified callable when the thread is next idle
# Callable is usually a function + its arguments wrapped with functools.partial
def runDeferred(callable):
    QtCore.QTimer.singleShot(0, callable)


class ListItemDelegate(QtWidgets.QItemDelegate):

    def __init__(self, *args):
        super(ListItemDelegate, self).__init__(*args)

    def sizeHint(self, option, index):
        size = super(ListItemDelegate, self).sizeHint(option, index)
        return QtCore.QSize(size.width()+10, size.height()*2)

    def createEditor(self, parent, option, index):
        editor = QtWidgets.QLineEdit(parent)
        return editor

    def setEditorData(self, editor, index):
        value = index.model().data(index, QtCore.Qt.EditRole)
        editor.setText(value)

    def setModelData(self, editor, model, index):
        src = index.model().data(index, QtCore.Qt.EditRole)
        dst = editor.text()
        res = cmds.rename(src, dst)
        model.setData(index, res, QtCore.Qt.EditRole)

    def drawDisplay(self, painter, option, rect, text):
        text = ''.join([' ' + text])
        r =  super(ListItemDelegate, self).drawDisplay(painter, option, rect, text)
        return r


class RenderElementDelegate(ListItemDelegate):

    def __init__(self, *args):
        super(RenderElementDelegate, self).__init__(*args)

    def createEditor(self, parent, option, index):
        if 0 < index.column():
            return None
        editor = QtWidgets.QLineEdit(parent)
        return editor

    def setEditorData(self, editor, index):
        if 0 < index.column():
            return None
        super(RenderElementDelegate, self).setEditorData(editor, index)

    def setModelData(self, editor, model, index):
        if 0 < index.column():
            return None
        super(RenderElementDelegate, self).setModelData(editor, model, index)


def insertRenderViewCaption(caption, insert_str):
    # captionはN行構成（各種情報の部分に insert_strを追記する）
    # 0: レンダラ名 \n
    # 1: 各種情報 \n    <----  ここに追加したい
    # N: ユーザー定義情報

    lines = caption.split('\n')
    line_index = 0
    if len(lines) >= 2 and len(lines[1]) > 0:
        line_index = 1

    lines[line_index] += insert_str
    return '\n'.join(lines)
